﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Configuration;
using System.Text.RegularExpressions;
using BlogHunter.Manager;

namespace BlogHunter
{
    class SohuBlog : Blog
    {
        private string _ebiLinkSpliceRule;
        public string EBILinkSpliceRule
        {
            get { return _ebiLinkSpliceRule; }
            set { _ebiLinkSpliceRule = value; }
        }

        public SohuBlog()
        {
            //Set Properties.
            AutoSplice = Convert.ToBoolean(ConfigurationSettings.AppSettings["SohuBlogHomePageAutoSplice"]);
            SpliceRule = ConfigurationSettings.AppSettings["SohuBlogHomePageSpliceRule"];
            OutPath = ConfigurationSettings.AppSettings["SohuOutPath"];

            EncodingCharset = ConfigurationSettings.AppSettings["SohuEncodingCharset"];

            //ReplacePatternBeforeExtract, used for removing peculiar HTML contents in Sina Blogs.
            ReplacePatternBeforeExtract = @"<h3>该日志已隐藏 </h3>";

            BlogInfoRegex = new Regex(@"<div class=""item-title"">([^<]*)<h3>([^&]*)&([^<]*)<a href=""([^""]*)"" target=""_blank"">([^<]*)</a>");
            LinkRegexGroupNum = Convert.ToInt32(ConfigurationSettings.AppSettings["SohuLinkRegexGroupNum"]);
            TitleRegexGroupNum = Convert.ToInt32(ConfigurationSettings.AppSettings["SohuTitleRegexGroupNum"]);

            DateRegexGroupNum = Convert.ToInt32(ConfigurationSettings.AppSettings["SohuDateRegexGroupNum"]);

            EBILinkSpliceRule = ConfigurationSettings.AppSettings["SohuEBILinkSpliceRule"];
        }

        public override string GetTargetHTMLContent(Uri targetUri, Encoding encodeType)
        {
            //Sohu should utilize GZip decoding method.
            return HTMLContentManager.GetGZipEncodedHTMLContent(targetUri, encodeType);
        }

        private string GetSohuEbiNum()
        {
            string ebiNum = string.Empty;
            string homepageContent = HTMLContentManager.GetGZipEncodedHTMLContent(BlogHomePage, Encoding.GetEncoding(EncodingCharset));

            Regex ediNumRegex = new Regex(@"var _ebi = '([0-9|a-z|A-Z]*)'");
            Match myMatch1 = ediNumRegex.Match(homepageContent);
            if (myMatch1.Success)
            {
                ebiNum = myMatch1.Groups[1].ToString().Trim();
            }

            return ebiNum;
        }

        public override void GetAllNewBlogInfoList()
        {
            //Loop Each Page to Get BlogInfo List

            //Get Ebi Number
            string ebiNumber = GetSohuEbiNum();

            int nextPageNum = 1;

            do
            {
                nextPageNum = GetNewBlogInfoList(nextPageNum, ebiNumber);
            } while (nextPageNum != -1);
        }


        public int GetNewBlogInfoList(int currentPageNum, string ebiNumber)
        {
            bool needUpadteFlag = true;
            int nextPageNum = currentPageNum + 1;

            Uri currentUri = new Uri(EBILinkSpliceRule.Replace("$BLOGNAME$", InputBlogName).Replace("$EBINUM$", ebiNumber).Replace("$PAGENUM$", currentPageNum.ToString()));

            String inputString = GetTargetHTMLContent(currentUri, Encoding.GetEncoding(EncodingCharset));

            //Replace Pattern Before Extract, Eg. We should remove Sina Blog Picture HTML contents before Extracting.
            if (!String.IsNullOrEmpty(ReplacePatternBeforeExtract))
            {
                inputString = Regex.Replace(inputString, ReplacePatternBeforeExtract, string.Empty);
            }

            Regex myRegex = BlogInfoRegex;
            if (myRegex.IsMatch(inputString))
            {
                Match myMatch = myRegex.Match(inputString);
                while (myMatch.Success)
                {
                    BlogInfo newBlogInfo = new BlogInfo();

                    string link = Regex.Replace(myMatch.Groups[LinkRegexGroupNum].Value.Replace("\r\n", " ").Trim(), @"( )\1+", "$1", RegexOptions.None);
                    Console.WriteLine(link);
                    newBlogInfo.ArticleLink = new Uri(currentUri, link).ToString();

                    string titleName = Regex.Replace(myMatch.Groups[TitleRegexGroupNum].Value.Replace("\r\n", " ").Trim(), @"( )\1+", "$1", RegexOptions.None);
                    Console.WriteLine(titleName);
                    newBlogInfo.ArticleTitle = titleName;


                    string strTimeString = string.Empty;//So difficult to fetch.
                    string strDateString = myMatch.Groups[DateRegexGroupNum].Value;

                    Console.WriteLine(strDateString + " " + strTimeString);

                    DateTime blogDatetime = DateTime.Now;
                    DateTime.TryParse(strDateString.Trim() + " " + strTimeString.Trim(), out blogDatetime);
                    newBlogInfo.ArticleDateTime = blogDatetime;


                    //If exists LatestPublishDate, break the while loop if newBlogInfo.ArticleDateTime < LatestPublishDate
                    if (LatestPublishDate != null && DateTime.Compare(newBlogInfo.ArticleDateTime, LatestPublishDate) < 0)
                    {
                        needUpadteFlag = false;
                        break;
                    }

                    //Add New BlogInfo to NewBlogInfoList if it doesn't exist in PreviousBlogInfoList
                    if (PreviousBlogInfoList != null && !PreviousBlogInfoList.Contains(newBlogInfo))
                    {
                        NewBlogInfoList.Add(newBlogInfo);
                    }
                    else
                    {
                        needUpadteFlag = false;
                        break;
                        //Console.WriteLine("Reduplicate BlogInfo, Need to break the loop.");
                    }

                    myMatch = myMatch.NextMatch();
                }
            }
            else
            {
                needUpadteFlag = false;
            }

            if (!needUpadteFlag)
                nextPageNum = -1;

            return nextPageNum;
        }

    }
}